home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
docs
/
tut3new
/
tut3.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-07
|
16KB
|
433 lines
/////////////////////////////////////////////////////////////////////////////
// //
// TUTPROG3.CPP - VGA Trainer Program 3 (in Turbo C++ 3.0) //
// //
// "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
// was limited to Pascal only in its first run. All I have done is taken //
// his original release, translated it to C++ and touched up a few things. //
// I take absolutely no credit for the concepts presented in this code and //
// am NOT the person to ask for help if you are having trouble. //
// //
// Program Notes : This program presents many new concepts, including: //
// Cirle and Line algorithms. //
// //
// If you are compiling this code command line, be sure to //
// use the "-ml" parameter (large memory model). //
// Otherwise, the program will compile and link, but will //
// lock up your system. //
// //
// Author : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za //
// Translator : Christopher G. Mann - r3cgm@dax.cc.uakron.edu //
// //
// Last Modified : December 7, 1994 //
// //
/////////////////////////////////////////////////////////////////////////////
// //
// INCLUDE FILES //
// //
#include <conio.h>
// getch(), clrscr(), kbhit()
#include <dos.h>
// MK_FP, Geninterrupt()
#include <math.h>
// floor(), ceil(), abs(), sin(), cos()
#include <iostream.h>
// cout, endl, memset(), _fmemset()
// //
// FUNCTION PROTOTYPES //
// //
// MODE SETTING FUNCTIONS
void SetMCGA();
void SetText();
// PALLETTE FUNCTIONS
void Pal (unsigned char ColorNo, unsigned char R,
unsigned char G, unsigned char B);
void PalPlay();
// SMALL UTILITY FUNCTIONS
int sgn (long a);
int round (long a);
// DRAWING FUNCTIONS
void Putpixel (int x, int y, unsigned char Col);
void Line (int a, int b, int c, int d, int col);
void Line2 (int x1, int y1, int x2, int y2, int col);
void Circle (int X, int Y, int rad, int col);
void WaitRetrace();
// //
// GLOBAL VARIABLE DECLARATIONS //
// //
// declare a pointer to the offset of VGA memory
unsigned char *vga = (unsigned char *) MK_FP(0xA000, 0);
// This declares the PALL variable. 0 to 255 signifies the colors of the
// pallette, 1 to 3 signifies the Red, Green and Blue values. I am
// going to use this as a sort of "virtual pallette", and alter it
// as much as I want, then suddenly bang it to screen. Pall2 is used
// to "remember" the origional pallette so that we can restore it at
// the end of the program. */
unsigned char Pall[256][3], Pall2[256][3];
///////////////////////////////////////////////////////////////////////////////
// //
// MAIN FUNCTION //
// //
///////////////////////////////////////////////////////////////////////////////
void main() {
clrscr();
cout
<< "This sample program will test out our line and circle algorithms.\n"
<< "In the first part, many circles will be draw creating (hopefully)\n"
<< "a ""tunnel"" effect. I will the rotate the pallete to make it look\n"
<< "nice. I will then draw some lines and rotate the pallette on them\n"
<< "too. Note : I am using the slower (first) line algorithm (in\n"
<< "procedure line2). Change it to Procedure Line and it will be using\n"
<< "the second line routine. NB : For descriptions on how pallette works\n"
<< "have a look at part two of this series; I won''t re-explain it here."
<< endl << endl;
cout
<< "Remember to send me any work you have done, I am most eager to help."
<< endl << endl;
cout
<< "Hit any key to continue ...";
getch();
SetMCGA();
// This sets colors 1 to 199 to values between 33 to 63. The MOD
// function gives you the remainder of a division, ie. 105 mod 10 = 5 }
for (int loop1=1; loop1<200; loop1++) {
Pall[loop1][0] = (loop1 % 30) + 33;
Pall[loop1][1] = 0;
Pall[loop1][2] = 0;
}
WaitRetrace();
// This sets the true pallette to variable Pall
for (loop1=1; loop1<200; loop1++)
Pal(loop1, Pall[loop1][0], Pall[loop1][1], Pall[loop1][2]);
// This draws 90 circles all with centers at 160,100 with increasing
// radii and colors.
for (loop1=1; loop1<91; loop1++)
Circle(160, 100, loop1, loop1);
// wait until a key is pressed
while (!kbhit()) PalPlay();
// make sure to clear the keyboard buffer
getch();
// This draws 199 lines, all starting at 0,1
for (loop1=1; loop1<200; loop1++)
Line2 (0,1,319,loop1,loop1); // *** Replace Line2 with Line to use the
// second line algorithm ***
while (!kbhit()) PalPlay();
getch();
getch();
SetText();
cout
<< "All done. Okay, so maybe it wasn''t a tunnel effect, but you get the\n"
<< "general idea ;-) This concludes the third sample program in the ASPHYXIA\n"
<< "Training series. You may reach DENTHOR under the name of GRANT SMITH\n"
<< "on the MailBox BBS, or leave a message to ASPHYXIA on the ASPHYXIA BBS\n"
<< "Get the numbers from Roblist, or write to :\n"
<< " Grant Smith\n"
<< " P.O. Box 270\n"
<< " Kloof\n"
<< " 3640\n" << endl;
cout << "I hope to hear from you soon!" << endl << endl;
cout << "Hit any key to exit ...";
getch();
}
/////////////////////////////////////////////////////////////////////////////
// //
// SetMCGA() - This function gets you into 320x200x256 mode. //
// //
/////////////////////////////////////////////////////////////////////////////
void SetMCGA() {
_AX = 0x0013;
geninterrupt (0x10);
}
/////////////////////////////////////////////////////////////////////////////
// //
// SetText() - This function gets you into text mode. //
// //
/////////////////////////////////////////////////////////////////////////////
void SetText() {
_AX = 0x0003;
geninterrupt (0x10);
}
/////////////////////////////////////////////////////////////////////////////
// //
// Pal() - This sets the Red, Green, and Blue values of a certain color. //
// //
/////////////////////////////////////////////////////////////////////////////
void Pal(unsigned char ColorNo, unsigned char R,
unsigned char G, unsigned char B) {
outp (0x03C8,ColorNo); // here is the pallette color I want to set
outp (0x03C9,R);
outp (0x03C9,G);
outp (0x03C9,B);
}
/////////////////////////////////////////////////////////////////////////////
// //
// PalPlay() - This function mucks about with our "virtual pallette", then //
// shoves it to the screen. //
// //
/////////////////////////////////////////////////////////////////////////////
void PalPlay() {
unsigned char Tmp[3];
// This copies color 199 from our virtual pallette to the Tmp variable.
_fmemmove(Tmp,Pall[199],3);
// This moves the entire virtual pallette up one color.
_fmemmove(Pall[2],Pall[1],199*3);
// This copies the Tmp variable to the bottom of the virtual pallette.
// Don't change 0: leave this always black to not change overscan color.
_fmemmove(Pall[1],Tmp,3);
WaitRetrace();
for (int loop1=0;loop1<256;loop1++)
Pal(loop1,Pall[loop1][0], Pall[loop1][1], Pall[loop1][2]);
}
/////////////////////////////////////////////////////////////////////////////
// //
// sgn() - This function is used by Line() to determine the sign of a long //
// //
/////////////////////////////////////////////////////////////////////////////
int sgn (long a) {
if (a > 0) return +1;
else if (a < 0) return -1;
else return 0;
}
/////////////////////////////////////////////////////////////////////////////
// //
// round() - This function is used by Line() to round a long to the //
// nearest integer. //
// //
/////////////////////////////////////////////////////////////////////////////
int round (long a) {
if ( (a - (int)a) < 0.5) return floor(a);
else return ceil(a);
}
/////////////////////////////////////////////////////////////////////////////
// //
// Putpixel() - This puts a pixel on the screen by writing directly to //
// memory. //
// //
/////////////////////////////////////////////////////////////////////////////
void Putpixel (int x, int y, unsigned char Col) {
memset(vga+(x+(y*320)),Col,1);
}
/////////////////////////////////////////////////////////////////////////////
// //
// Line() - This draws a line from a,b to c,d of color col. //
// This function will be explained in more detail in tut3new.zip //
// //
/////////////////////////////////////////////////////////////////////////////
void Line(int a, int b, int c, int d, int col) {
long u,s,v,d1x,d1y,d2x,d2y,m,n;
int i;
u = c-a; // x2-x1
v = d-b; // y2-y1
d1x = sgn(u); // d1x is the sign of u (x2-x1) (VALUE -1,0,1)
d1y = sgn(v); // d1y is the sign of v (y2-y1) (VALUE -1,0,1)
d2x = sgn(u); // d2x is the sign of u (x2-x1) (VALUE -1,0,1)
d2y = 0;
m = abs(u); // m is the distance between x1 and x2
n = abs(v); // n is the distance between y1 and y2
if (m<=n) { // if the x distance is greater than the y distance
d2x = 0;
d2y = sgn(v); // d2y is the sign of v (x2-x1) (VALUE -1,0,1)
m = abs(v); // m is the distance between y1 and y2
n = abs(u); // n is the distance between x1 and x2
}
s = (int)(m / 2); // s is the m distance (either x or y) divided by 2
for (i=0;i<round(m);i++) { // repeat this loop until it
// is = to m (y or x distance)
Putpixel(a,b,col); // plot a pixel at the original x1, y1
s += n; // add n (dis of x or y) to s (dis of x of y)
if (s >= m) { // if s is >= m (distance between y1 and y2)
s -= m;
a += d1x;
b += d1y;
}
else {
a += d2x;
b += d2y;
}
}
}
/////////////////////////////////////////////////////////////////////////////
// //
// Line2() - This function draws a line from x1,y1 to x2,y2 using the //
// first method. //
// //
/////////////////////////////////////////////////////////////////////////////
void Line2(int x1, int y1, int x2, int y2, int col) {
int x, y, xlength, ylength, dx, dy;
float xslope, yslope;
xlength = abs(x1-x2);
if ((x1-x2) < 0) dx = -1;
if ((x1-x2) == 0) dx = 0;
if ((x1-x2) > 0) dx = +1;
ylength = abs(y1-y2);
if ((y1-y2) < 0) dy = -1;
if ((y1-y2) == 0) dy = 0;
if ((y1-y2) > 0) dy = +1;
if (dy == 0) {
if (dx < 0)
for (x=x1; x<x2+1; x++)
Putpixel (x,y1,col);
if (dx > 0)
for (x=x2; x<x1+1; x++)
Putpixel (x,y1,col);
}
if (dx == 0) {
if (dy < 0)
for (y=y1; y<y2+1; y++)
Putpixel (x1,y,col);
if (dy > 0)
for (y=y2; y<y1+1; y++)
Putpixel (x1,y,col);
}
if ((xlength != 0) && (ylength != 0)) {
xslope = (float)xlength/(float)ylength;
yslope = (float)ylength/(float)xlength;
}
else {
xslope = 0.0;
yslope = 0.0;
}
if ((xslope != 0) && (yslope != 0) &&
(yslope/xslope < 1) && (yslope/xslope > -1)) {
if (dx < 0)
for (x=x1; x<x2+1; x++) {
y = round (yslope*x);
Putpixel (x,y,col);
}
if (dx > 0)
for (x=x2; x<x1+1; x++) {
y = round (yslope*x);
Putpixel (x,y,col);
}
}
else {
if (dy < 0)
for (y=x1; y<x2+1; y++) {
x = round (xslope*y);
Putpixel (x,y,col);
}
if (dy > 0)
for (y=x2; y<x1+1; y++) {
x = round (xslope*y);
Putpixel (x,y,col);
}
}
}
/////////////////////////////////////////////////////////////////////////////
// //
// Circle() - This draws a circle with center X,Y, with Rad as its radius. //
// //
/////////////////////////////////////////////////////////////////////////////
void Circle(int X, int Y, int rad, int col) {
float deg = 0;
do {
X = round(rad * cos(deg));
Y = round(rad * sin(deg));
Putpixel (X+160, Y+100, col);
deg += 0.005;
}
while (deg <= 6.4);
}
/////////////////////////////////////////////////////////////////////////////
// //
// WaitRetrace() - This waits until you are in a Verticle Retrace. //
// //
/////////////////////////////////////////////////////////////////////////////
void WaitRetrace() {
_DX = 0x03DA;
l1: asm {
in al,dx;
and al,0x08;
jnz l1;
}
l2: asm {
in al,dx;
and al,0x08;
jz l2;
}
}